//CSE 430 - Operating Systems
//Partha Dasgupta
//Spring '12
//Project 3

//Alan Tu
//Kelly Jesionowski

#ifndef _SEM_H
#define _SEM_H

#include "threads.h"

//semaphore data structure - a value field and a queue of TCBs

//initSem(sem, value) - initializes the value field with the specified value

//P(sem) - the P routine decrements the semaphore, and if the value is less than zero then blocks the process in the queue associated with the semaphore

//V(sem) - the V routine increments the semaphore, and if the value is 0 or negative, then takes a PCB out of the semaphore queue and puts it into the run
//  queue. Note: the V routine also "yields" to the next runnable process (this is important)

typedef struct semaphore{
    int count;
    TCB_t *queue;
}semaphore_t;

initSem(semaphore_t **sem, int value){
    *sem = (semaphore_t *)malloc(sizeof(semaphore_t));

    (*sem)->count = value;
    (*sem)->queue = NULL;
}

//wait() operation
P(semaphore_t **sem)
{
    (*sem)->count--;
    if((*sem)->count < 0) {
        //printf(" waiting...\n");
        sleep(1);
        TCB_t *temp = DelQueue(&readyQ);
        AddQueue(&((*sem)->queue), temp);
        swapcontext(&(temp->context), &(readyQ->context)); //(from, to)
    }
    yield();
}

//signal() operation
V(semaphore_t **sem)
{
    (*sem)->count++;
    if((*sem)->count <= 0) {
        //printf(" signaling...\n");
        TCB_t *temp = DelQueue(&(*sem)->queue);
        AddQueue(&readyQ, temp);
    }
    sleep(1);
    yield();
}

#endif //_SEM_H
